<template>
  <div ref="html2canvas" id="qaOnline" style="position: relative; background-color: Gainsboro">
    <el-card>
      <el-row>
        <el-col :span="23" :xs="24">
          <el-form :inline="true" label-width="90px">
            <el-form-item :label="'验收状态：'" :label-position="'left'" style="margin-top: -5px; margin-bottom: -30px">
              {{ currentStatus }}
            </el-form-item>
            <el-form-item style="margin-top: -5px; margin-bottom: -30px">
              <el-input id="remarkInput" type="text" placeholder="批注" size="mini" v-model="remark" />
            </el-form-item>
            <el-form-item style="margin-top: -5px; margin-bottom: -30px">
              <el-tooltip effect="dark" content="通过" placement="bottom">
                <el-button type="success" size="mini" @click="handleComments('通过')" icon="el-icon-check" circle />
              </el-tooltip>
            </el-form-item>
            <el-form-item style="margin-top: -5px; margin-bottom: -30px">
              <el-tooltip effect="dark" content="驳回" placement="bottom">
                <el-button type="danger" size="mini" @click="handleComments('驳回')" icon="el-icon-close" circle />
              </el-tooltip>
            </el-form-item>
            <el-form-item style="margin-top: -5px; margin-bottom: -30px">
              <el-tooltip effect="dark" content="挂起" placement="bottom">
                <el-button type="warning" size="mini" @click="handleComments('挂起')" icon="el-icon-sort-down" circle />
              </el-tooltip>
            </el-form-item>
            <el-form-item style="margin-top: -5px; margin-bottom: -30px">
              <el-tooltip effect="dark" content="全屏" placement="bottom">
                <el-button
                  v-if="!isFullscreen"
                  type="primary"
                  size="mini"
                  @click="threejsFullScreen()"
                  icon="el-icon-full-screen"
                  circle
                />
              </el-tooltip>
              <el-tooltip effect="dark" content="退出全屏" placement="bottom">
                <el-button
                  v-if="isFullscreen"
                  type="primary"
                  size="mini"
                  @click="threejsFullScreen()"
                  icon="el-icon-aim"
                  circle
                />
              </el-tooltip>
            </el-form-item>
            <el-form-item v-if="markType !== 10" style="margin-top: -5px; margin-bottom: -30px">
              <el-input id="trackID" type="text" placeholder="TrackID" size="mini" v-model="selectedObject.a1" />
            </el-form-item>
            <el-form-item v-if="markType !== 10" style="margin-top: -5px; margin-bottom: -30px">
              <el-tooltip effect="dark" content="查找TrackId" placement="bottom">
                <el-button
                  type="primary"
                  size="mini"
                  @click="sync_highlight_objects('', selectedObject, undefined)"
                  icon="el-icon-search"
                  circle
                />
              </el-tooltip>
            </el-form-item>
            <el-form-item style="margin-top: -5px; margin-bottom: -30px">
              <el-tooltip effect="dark" content="批注列表" placement="bottom">
                <el-button
                  type="primary"
                  size="mini"
                  @click="
                    () => {
                      remarkListVisable = !remarkListVisable
                      this.$refs.remarkList.show(remarkListVisable)
                    }
                  "
                  icon="el-icon-notebook-2"
                  circle
                />
              </el-tooltip>
            </el-form-item>
            <el-form-item v-show="radarView" style="margin-top: -5px; margin-bottom: -30px">
              <el-tooltip effect="dark" content="融合浏览" placement="bottom">
                <el-button type="primary" size="mini" @click="goRaderView" icon="el-icon-video-camera-solid" circle />
              </el-tooltip>
            </el-form-item>
            <el-form-item
              v-if="fileList[currentIndex] && fileList[currentIndex].updateBy && !checkrole(['qa'])"
              :label="'标注员：'"
              :label-position="'left'"
              style="margin-top: -5px; margin-bottom: -30px"
            >
              {{ fileList[currentIndex].updateBy }}
            </el-form-item>
            <el-form-item
              v-if="fileList[currentIndex] && fileList[currentIndex].updateTime && !checkrole(['qa'])"
              :label="'更新时间：'"
              :label-position="'left'"
              style="margin-top: -5px; margin-bottom: -30px"
            >
              {{ fileList[currentIndex].updateTime }}
            </el-form-item>
          </el-form>
        </el-col>
        <el-col :span="1" :xs="24">
          <el-form :inline="true" label-width="68px">
            <el-form-item style="margin-top: -5px; margin-bottom: -30px">
              <el-tooltip effect="dark" content="返回文件列表" placement="bottom">
                <el-button type="primary" icon="el-icon-d-arrow-left" size="mini" @click="returnFileList()" circle />
              </el-tooltip>
            </el-form-item>
          </el-form>
        </el-col>
      </el-row>
    </el-card>
    <div style="position: relative; height: 83vh">
      <CubeAttribute
        v-bind:attrs-view-drawer="attrsViewDrawer"
        v-bind:selected-object="selectedObject"
        v-bind:cube-info="cubeInfo"
      />
      <SliderContainer v-on:content-resize="onWindowResize" v-bind:height="83 + 'vh'" v-bind:mark-type="markType">
        <template slot="left">
          <picture-list
            ref="pictureList"
            v-bind:height="83"
            v-bind:task-id="queryParams.taskId"
            v-bind:hide-tip="HideTip"
            v-bind:show-tip="ShowTip"
            v-bind:attribute-names="attributeNames"
            v-bind:color-names="colorNames"
            v-bind:sync_highlight_objects="sync_highlight_objects"
            v-bind:sync_clear_highlight_objects="sync_clear_highlight_objects"
            v-bind:set-position="setPosition"
            v-bind:elements-remark="elementsRemark"
            v-bind:handle-element-comments="remarkFormOpen"
            v-bind:change-cube-info="changeCubeInfo"
            v-bind:change-list="changeList"
            v-bind:add-pic-mark-annotation="addPicMarkAnnotation"
            v-bind:submit-annotations="submitAnnotations"
          ></picture-list>
        </template>
        <template slot="right">
          <!--div align="center" v-if="fileList[currentIndex]">
            {{ fileList[currentIndex].fileId }}
          </div-->
          <point-cloud
            ref="pointCloud"
            v-bind:height="83"
            v-bind:task-id="queryParams.taskId"
            v-bind:hide-tip="HideTip"
            v-bind:show-tip="ShowTip"
            v-bind:attribute-names="attributeNames"
            v-bind:render-type="renderType"
            v-bind:camera-position="cameraPosition"
            v-bind:high-light-cube-points="highLightCubePoints"
            v-bind:color-names="colorNames"
            v-bind:is-loading="isLoading"
            v-bind:loading="loading"
            v-bind:sync_highlight_objects="sync_highlight_objects"
            v-bind:sync_clear_highlight_objects="sync_clear_highlight_objects"
            v-bind:change-page="changePage"
            v-bind:set-position="setPosition"
            v-bind:elements-remark="elementsRemark"
            v-bind:handle-element-comments="remarkFormOpen"
            v-bind:change-cube-info="changeCubeInfo"
            v-bind:add-split-mark-annotation="addSplitMarkAnnotation"
          ></point-cloud>
        </template>
      </SliderContainer>
    </div>
    <div id="bottomDiv" class="bottom-div">
      <el-progress
        :percentage="cachePercentage"
        color="blue"
        v-show="cachePercentage > 0 && cachePercentage < 100"
        status="exception"
      ></el-progress>
      <el-row :gutter="20">
        <el-col :span="8" :xs="24">
          <el-form :inline="true">
            <el-form-item style="display: table-cell; width: 100%; text-align: left">
              <div class="filename">
                <span>{{ taskPath }}</span>
              </div>
            </el-form-item>
          </el-form>
        </el-col>
        <el-col :span="8" :xs="24">
          <el-form align="center">
            <el-form-item style="">
              <el-button
                v-if="!playStarted"
                :disabled="cacheStatus.cacheIndex < currentIndex - 30"
                type="primary"
                size="mini"
                @click="startPlay()"
                icon="el-icon-caret-right"
                circle
              />
              <el-button
                v-if="playStarted"
                type="primary"
                size="mini"
                @click="pausePlay()"
                icon="el-icon-video-pause"
                circle
              />
              <el-button
                type="primary"
                size="mini"
                :disabled="loading || currentIndex <= 0"
                @click="changePage(-1)"
                icon="el-icon-back"
                circle
              />
              <span
                >&nbsp;&nbsp;&nbsp;&nbsp;当前：({{ currentIndex + 1 }} /
                {{ fileList.length }})&nbsp;&nbsp;&nbsp;&nbsp;</span
              >
              <el-button
                type="primary"
                size="mini"
                :disabled="loading || currentIndex >= fileList.length - 1"
                @click="changePage(1)"
                icon="el-icon-right"
                circle
              />
              &nbsp;
              <el-select
                :value="currentIndex + 1"
                @change="
                  (value) => {
                    changePage(value - 1 - currentIndex)
                  }
                "
                style="width: 80px"
              >
                <el-option v-for="(item, index) in fileList" :key="item.fileId" :label="index + 1" :value="index + 1">
                </el-option>
              </el-select>
            </el-form-item>
          </el-form>
        </el-col>
        <el-col :span="8" :xs="24">
          <el-form :inline="true">
            <el-form-item style="display: table-cell; width: 100%; text-align: right">
              <div class="filename">
                <span v-if="fileList[currentIndex]">{{ fileList[currentIndex].fileId }}&nbsp;</span>
              </div>
            </el-form-item>
            <!-- 标注物体列表 -->
            <el-form-item style="display: table-cell">
              <el-button
                @click="
                  annotationDialogVisible = true
                  queryAnnotationList()
                "
                type="text"
                >标注列表</el-button
              >
            </el-form-item>
            <el-form-item style="display: table-cell">
              <el-popover
                placement="top-end"
                width="360"
                :visible-arrow="false"
                trigger="click"
                @show="showColorDialogVar = true"
                @hide="showColorDialogVar = false"
              >
                <div>
                  <div id="colorPanel" class="icon-list">
                    <div>
                      <p>属性色块：</p>
                    </div>
                    <div class="color-name" v-for="dict in colorNames" :key="dict.dictValue">
                      <svg :style="'height: 18px;width: 18px;'">
                        <rect width="18px" height="18px" :style="'fill:' + dict.dictLabel" />
                      </svg>
                      <span>{{ getLabelName(dict.dictValue) }} </span>
                    </div>
                  </div>
                </div>
                <el-button slot="reference" type="text" :disabled="isFullscreen" class="color-name-btn">
                  色块
                  <i
                    style="transform: rotate(90deg)"
                    :class="showColorDialogVar ? 'el-icon-d-arrow-right' : 'el-icon-d-arrow-left'"
                  ></i>
                </el-button>
              </el-popover>
            </el-form-item>
          </el-form>
        </el-col>
      </el-row>
    </div>

    <!-- 标注目标对话框 -->
    <el-dialog
      :title="'标注目标列表'"
      :visible.sync="annotationDialogVisible"
      :fullscreen="annotationDialogFullScreen"
      :close-on-click-modal="false"
      :show-close="true"
      width="50%"
      center
    >
      <template slot="title">
        <div class="avue-crud__dialog__header">
          <span class="el-dialog__title">
            <span
              style="
                display: inline-block;
                background-color: #3478f5;
                width: 3px;
                height: 20px;
                margin-right: 5px;
                float: left;
                margin-top: 2px;
              "
            ></span>
            标注目标列表
          </span>
          <div class="avue-crud__dialog__menu" @click="annotationDialogFullScreen = !annotationDialogFullScreen">
            <i class="el-icon-full-screen"></i>
          </div>
        </div>
      </template>
      <div>
        <el-row :gutter="10" class="mb8">
          <el-col :span="1.5">
            <el-button
              type="danger"
              @click="handleAnnotationDelete"
              icon="el-icon-delete"
              size="mini"
              :disabled="multiple"
              >删除</el-button
            >
          </el-col>
        </el-row>
        <el-table
          @row-click="onAnnotationRowSelect"
          :data="annotationList"
          @selection-change="handleSelectionChange"
          ref="fileTable"
          style="max-height: 75vh; overflow: auto"
        >
          <el-table-column type="selection" width="55" align="center" />
          <el-table-column
            label="格式"
            align="center"
            width="80px"
            prop="fileType"
            :formatter="
              (row) => {
                return row.fileType == '2d' ? '二维' : '三维'
              }
            "
          />
          <el-table-column label="类别" align="left" width="120px" prop="name" :formatter="annotationNameFormatter" />
          <el-table-column label="操作" align="center" width="160px" class-name="small-padding fixed-width">
            <template slot-scope="scope">
              <el-button size="mini" type="text" icon="el-icon-document" @click="handleAnnotationUpdate(scope.row)"
                >修改</el-button
              >
              <el-button size="mini" type="text" icon="el-icon-delete" @click="handleAnnotationDelete(scope.row)"
                >删除</el-button
              >
            </template>
          </el-table-column>
          <el-table-column
            label="属性a1"
            align="left"
            width="75px"
            prop="a1"
            :formatter="annotationAttributeFormatter"
          />
          <el-table-column
            label="属性a2"
            align="left"
            width="75px"
            prop="a2"
            :formatter="annotationAttributeFormatter"
          />
          <el-table-column
            label="属性a3"
            align="left"
            width="75px"
            prop="a3"
            :formatter="annotationAttributeFormatter"
          />
          <el-table-column
            label="属性a4"
            align="left"
            width="75px"
            prop="a4"
            :formatter="annotationAttributeFormatter"
          />
          <el-table-column
            label="属性a5"
            align="left"
            width="75px"
            prop="a5"
            :formatter="annotationAttributeFormatter"
          />
          <el-table-column
            label="属性a6"
            align="left"
            width="75px"
            prop="a6"
            :formatter="annotationAttributeFormatter"
          />
          <el-table-column
            label="属性a7"
            align="left"
            width="75px"
            prop="a7"
            :formatter="annotationAttributeFormatter"
          />
          <el-table-column
            label="属性a8"
            align="left"
            width="75px"
            prop="a8"
            :formatter="annotationAttributeFormatter"
          />
          <el-table-column
            label="属性b1"
            align="left"
            width="75px"
            prop="b1"
            :formatter="annotationAttributeFormatter"
          />
          <el-table-column
            label="属性b2"
            align="left"
            width="75px"
            prop="b2"
            :formatter="annotationAttributeFormatter"
          />
          <el-table-column
            label="属性b3"
            align="left"
            width="75px"
            prop="b3"
            :formatter="annotationAttributeFormatter"
          />
          <el-table-column
            label="属性b4"
            align="left"
            width="75px"
            prop="b4"
            :formatter="annotationAttributeFormatter"
          />
          <el-table-column
            label="属性b5"
            align="left"
            width="75px"
            prop="b5"
            :formatter="annotationAttributeFormatter"
          />
          <el-table-column
            label="属性b6"
            align="left"
            width="75px"
            prop="b6"
            :formatter="annotationAttributeFormatter"
          />
          <el-table-column
            label="属性b7"
            align="left"
            width="75px"
            prop="b7"
            :formatter="annotationAttributeFormatter"
          />
          <el-table-column
            label="属性b8"
            align="left"
            width="75px"
            prop="b8"
            :formatter="annotationAttributeFormatter"
          />
        </el-table>
      </div>
    </el-dialog>

    <!-- 添加批注对话框 -->
    <el-dialog append-to-body :title="'目标信息'" :visible.sync="detailsDialogOpen" width="600px">
      <el-form :model="selectedObject" label-position="right" label-width="80px">
        <el-form-item v-for="attribute in selectedObject.attributes" :key="attribute.key" :label="attribute.key + ': '">
          <el-input v-model="attribute.value" maxlength="50" readonly />
        </el-form-item>
        <el-form-item label="错误类型" prop="errorType">
          <el-select
            v-model="selectedObject.errorType"
            @change="errorTypeSelectChanged"
            placeholder="请选择错误类型"
            clearable
            size="small"
          >
            <el-option
              v-for="dict in errorTypeOptions"
              :key="dict.dictValue"
              :label="dict.dictLabel"
              :value="dict.dictValue"
            />
          </el-select>
        </el-form-item>
        <el-form-item :label="'目标批注: '">
          <el-input
            id="detailRemarkInput"
            maxlength="80"
            placeholder="请在此输入针对改目标的批注"
            v-model="selectedObject.remark"
          />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button
          type="primary"
          @click="
            handleElementComments(
              selectedObject.a1 ? selectedObject.a1 + '' : selectedObject.mMarkAnnotationId + '',
              selectedObject.remark
            )
          "
          >提 交</el-button
        >
        <el-button @click="cancelHandleElementComments()">取 消</el-button>
      </div>
    </el-dialog>

    <!-- 属性修改对话框 -->
    <el-dialog :title="annotationInfoDialogTitle" :visible.sync="annotationInfoDialogOpen" width="600px" append-to-body>
      <!-- el-form ref="form" :model="form" :rules="labelRules" label-width="160px"-->
      <el-form ref="form" :model="form" label-width="200px">
        <el-form-item label="应用范围">
          <el-checkbox
            v-model="form.applyFullTask"
            :checked="form.applyFullTask"
            :disabled="form.applyFollowResult"
            label="应用到所有帧"
          ></el-checkbox>
          <el-checkbox
            v-model="form.applyFollowResult"
            :checked="form.applyFollowResult"
            :disabled="form.applyFullTask"
            label="应用到后续帧"
          ></el-checkbox>
        </el-form-item>
        <el-form-item label="类型" prop="name">
          <el-select v-model="form.name" placeholder="请选择类型" @change="annotationNameChanged(form.name)">
            <el-option v-for="(value, key) in formOptions.name" :key="key" :label="value" :value="key" />
          </el-select>
        </el-form-item>
        <div v-if="selectedObject.type == '3d'">
          <el-form-item v-for="i in 8" :label="formOptions['a' + i + '_3d_description']" :prop="'a' + i" :key="i">
            <el-input
              v-if="
                formOptions['a' + i + '_3d'] &&
                Object.getOwnPropertyNames(formOptions['a' + i + '_3d']).length == 0 &&
                selectedObject.type == '3d' &&
                formOptions.a1_3d_description
              "
              v-model="form.a1"
              :placeholder="'请选择' + formOptions.a1_3d_description"
              size="mini"
            />
            <el-select
              v-if="
                formOptions['a' + i + '_3d'] &&
                Object.getOwnPropertyNames(formOptions['a' + i + '_3d']).length > 0 &&
                selectedObject.type == '3d' &&
                formOptions['a' + i + '_3d_description']
              "
              v-model="form['a' + i]"
              :placeholder="'请选择' + formOptions['a' + i + '_3d_description']"
            >
              <el-option v-for="(value, key) in formOptions['a' + i + '_3d']" :key="key" :label="value" :value="key" />
            </el-select>
          </el-form-item>
        </div>
        <div v-if="selectedObject.type == '2d'">
          <el-form-item v-for="i in 8" :label="formOptions['a' + i + '_2d_description']" :prop="'a' + i" :key="i">
            <el-input
              v-if="
                formOptions['a' + i + '_2d'] &&
                Object.getOwnPropertyNames(formOptions['a' + i + '_2d']).length == 0 &&
                selectedObject.type == '2d' &&
                formOptions.a1_2d_description
              "
              v-model="form.a1"
              :placeholder="'请选择' + formOptions.a1_2d_description"
              size="mini"
            />
            <el-select
              v-if="
                formOptions['a' + i + '_2d'] &&
                Object.getOwnPropertyNames(formOptions['a' + i + '_2d']).length > 0 &&
                selectedObject.type == '2d' &&
                formOptions['a' + i + '_2d_description']
              "
              v-model="form['a' + i]"
              :placeholder="'请选择' + formOptions['a' + i + '_2d_description']"
            >
              <el-option v-for="(value, key) in formOptions['a' + i + '_2d']" :key="key" :label="value" :value="key" />
            </el-select>
          </el-form-item>
        </div>
        <div v-if="selectedObject.type == '3d'">
          <el-form-item v-for="i in 8" :label="formOptions['b' + i + '_3d_description']" :prop="'b' + i" :key="i">
            <el-select
              v-if="selectedObject.type == '3d' && formOptions['b' + i + '_3d_description']"
              v-model="form['b' + i]"
              :placeholder="'请选择' + formOptions['b' + i + '_3d_description']"
            >
              <el-option v-for="(value, key) in formOptions['b' + i + '_3d']" :key="key" :label="value" :value="key" />
            </el-select>
          </el-form-item>
        </div>
        <div v-if="selectedObject.type == '2d'">
          <el-form-item v-for="i in 8" :label="formOptions['b' + i + '_2d_description']" :prop="'b' + i" :key="i">
            <el-select
              v-if="selectedObject.type == '2d' && formOptions['b' + i + '_2d_description']"
              v-model="form['b' + i]"
              :placeholder="'请选择' + formOptions['b' + i + '_2d_description']"
            >
              <el-option v-for="(value, key) in formOptions['b' + i + '_2d']" :key="key" :label="value" :value="key" />
            </el-select>
          </el-form-item>
        </div>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click.native.prevent="submitUpdateForm">确 定</el-button>
        <el-button @click="cancelUpdateForm">取 消</el-button>
      </div>
    </el-dialog>

    <!-- 点云分割目标选择对话框 -->
    <el-dialog title="选择待修改目标" :visible.sync="updateSplitInfoDialogOpen" width="480px" append-to-body>
      <el-form ref="updateSplitInfoForm" :model="updateSplitInfoForm" label-width="160px">
        <el-form-item label="类型" prop="name">
          <el-select v-model="updateSplitInfoForm.mMarkAnnotationId" placeholder="请选择类型">
            <el-option
              v-for="item in annotationList"
              :key="item.mMarkAnnotationId"
              :label="annotationNameFormatter(item)"
              :value="item.mMarkAnnotationId"
            />
          </el-select>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitUpdateSplitInfoForm">确 定</el-button>
        <el-button @click="cancelUpdateSplitInfoForm">取 消</el-button>
      </div>
    </el-dialog>

    <div id="focus_toolTip" class="special_focus_toolTip" v-html="toolTopbody" />
    <RemarkList
      ref="remarkList"
      :task-id="queryParams.taskId"
      :set-position="setPosition"
      :delete-remark="deleteRemark"
      :update-remark="updateRemark"
    />
  </div>
</template>

<script>
import $ from 'jquery'
import {
  getMarkAnnotations,
  pointsCloudDetails,
  getImageWithCache,
  getPcdFileWithCache,
} from '@/api/mark/onlineCheckV1'
import {
  annotationList,
  addAnnotation,
  updateAnnotation,
  updateAnnotationAttributes,
  deleteAnnotation,
  copyPreviousAnnotation,
} from '@/api/mark/markAnnotation'
import { listResult, updateResult } from '@/api/mark/qaresult'
import { getQaTask } from '@/api/mark/qaTask'
import screenfull from 'screenfull'
import { checkRole } from '@/utils/permission'
import PictureList from './components/PictureList'
import PointCloud from './components/PointCloud'
import SliderContainer from './components/SliderContainer'
import RemarkList from './components/RemarkList'
import CubeAttribute from './components/CubeAttribute'
import { listRemarkBall, addRemarkBall } from '@/api/mark/remarkBall'
import { Dictionary } from '@/utils/dictionary'
import html2canvas from 'html2canvas'
import './whammy.js'

const ROUTE_PATH = Object.freeze({
  editor_2d: '/mark/editor2d',
  radar_view: '/mark/RadarView',
  mark_result: '/mark/result',
})

export default {
  name: 'FuseEditorV1',
  components: {
    SliderContainer,
    PictureList,
    PointCloud,
    RemarkList,
    CubeAttribute,
  },
  computed: {
    markAnnotations() {
      return this.$store.state.markData.markAnnotations
    },
  },
  data() {
    return {
      playCachePromise: undefined,
      playing: false,
      playStarted: false,
      taskPath: '',
      seconds: 0,
      interval: undefined,
      playIndex: 0,
      scaleFactor: undefined,
      showAttributesText: true,
      animationFrameId: undefined,
      mouseDown: false,
      renderEnabled: false,
      pointTextFontSize: 48,
      detailsDialogOpen: false,
      showColorDialogVar: false,
      isFullscreen: false,
      queryParams: {
        taskId: undefined,
        mQaResultId: undefined,
      },
      selectedObject: {
        a1: '',
        remark: '',
        attributes: [],
        type: '',
        imageIndex: '',
        errorType: '',
        mPoint: { x: -1, y: -1, z: -1 },
        elementInstance: null,
        position: null,
      },
      cubeInfo: { width: '', height: '', length: '' },
      errorTypeOptions: [],
      currentSelection: {},
      colorNames: {},
      attributeNames: {},
      imgCount: 0,
      markType: 0,
      tipContent: '',
      colorBody: '',
      toolTopbody: '',
      remarkMap: new Map(), // 批注图标
      loading: false,

      currentStatus: '',
      currentIndex: -1,
      fileList: {},
      remark: '',
      elementsRemark: {},
      renderType: '',
      highLightCubePoints: 'false',
      cameraPosition: null,
      selectedObjectA1: null,
      attrsViewDrawer: false,
      changeList: new Dictionary(),
      annotationInfoDialogTitle: '',
      annotationInfoDialogOpen: false,
      updateSplitInfoDialogOpen: false,
      // 属性修改表单参数
      form: {
        applyFullTask: false,
        applyFollowResult: false,
        mMarkAnnotationId: undefined,
        name: undefined,
        a1: undefined,
        a2: undefined,
        a3: undefined,
        a4: undefined,
        a5: undefined,
        a6: undefined,
        a7: undefined,
        a8: undefined,
        b1: undefined,
        b2: undefined,
        b3: undefined,
        b4: undefined,
        b5: undefined,
        b6: undefined,
        b7: undefined,
        b8: undefined,
        fileName: undefined,
      },
      labelRules: {
        name: [{ required: true, trigger: 'blur', message: '类型不能为空' }],
      },
      updateSplitInfoForm: {
        mMarkAnnotationId: undefined,
      },
      formOptions: {},
      remarkListVisable: false,
      cacheStatus: {
        taskId: null,
        cacheIndex: 0,
        started: false,
      },
      cacheStatusVersion: 0,
      cachePercentage: 0,
      lastPlayTime: null,
      hideOther: false,
      radarView: false,
      autoAnnotation: false,
      encoder: null,
      annotationListVisible: false,
      annotationList: null,
      annotationTotal: 0,
      annotationQueryParams: {
        mQaResultId: undefined,
      },
      splitMap: new Map(),
      annotationDialogVisible: false,
      annotationDialogFullScreen: false,
      annotationDialogMinimize: false,
      multiple: true,
      ids: null,
    }
  },
  methods: {
    checkrole(role) {
      return checkRole(role)
    },
    goRaderView() {
      const { queryParams, fileList, currentIndex } = this

      this.$router.push({
        path: ROUTE_PATH.radar_view,
        query: {
          taskId: queryParams.taskId,
          mQaResultId: fileList[currentIndex].mQaResultId,
        },
      })
    },
    // 批注列表点击后图片和点云矩形缩放定位
    setPosition(a1, mQaResultId, remark, type, imageIndex, errorType, point, position) {
      if (!a1 && !position) return
      this.selectedObjectA1 = a1
      if (this.$route.query.index) {
        if (parseInt(this.$route.query.index) - this.currentIndex - 1 != 0)
          this.changePage(parseInt(this.$route.query.index) - this.currentIndex - 1)
      }
      if (this.markType === 10) return
      this.selectedObject.a1 = a1
      this.selectedObject.remark = remark
      this.selectedObject.type = type
      this.selectedObject.imageIndex = imageIndex
      this.selectedObject.errorType = errorType
      this.selectedObject.position = position
      if (type == '2d') {
        this.selectedObject.attributes = this.$refs.pictureList.getSelectedObjectAttributes(a1, imageIndex)
      } else if (type == '3d') {
        this.selectedObject.attributes = this.$refs.pointCloud.getSelectedObjectAttributes(a1)
      }
      this.sync_highlight_objects('', this.selectedObject)
    },
    // 批注列表删除批注后更新图片和点云显示的批注图标
    deleteRemark(a1, type, elementsRemarkKey) {
      this.removeCache(this.fileList[this.currentIndex].mQaResultId)
      this.changePage(0)
      // 这里处理重新打开批注弹框时的remark input值
      // if (this.selectedObject.a1 == a1 && type && this.selectedObject.type == type) {
      //   this.selectedObject.remark = ''
      // }

      // // 删除 this.elementsRemark 对应的记录
      // let item = this.remarkMap.get(elementsRemarkKey);
      // if (item && type == '2d') {
      //   item.remove();
      //   item.markRemarkId && item.textObject.remove();
      // }

      // this.elementsRemark[elementsRemarkKey] = null;
      // this.elementsRemark['ball-' + elementsRemarkKey] = null;
      // this.remarkMap.delete(elementsRemarkKey);
      // if(type === "3d")
      //   this.$refs.pointCloud.reRender();
      // if(type === "2d")
      //   this.$refs.pictureList.reRender();
    },
    // 批注列表更新批注后更新缓存批注数据
    updateRemark(a1, type, elementsRemarkKey, remark) {
      // 这里处理重新打开批注弹框时的remark input值
      if (this.selectedObject.a1 == a1 && type && this.selectedObject.type == type) {
        this.selectedObject.remark = remark
      }

      this.elementsRemark[elementsRemarkKey] = remark
      if (this.elementsRemark['ball-' + elementsRemarkKey]) {
        this.elementsRemark['ball-' + elementsRemarkKey].remark = remark
      }

      // if(type === "3d")
      //   this.$refs.pointCloud.reRender();
      // if(type === "2d")
      //   this.$refs.pictureList.reRender();
    },
    errorTypeSelectChanged(value) {
      for (let i = 0; i < this.errorTypeOptions.length; i++) {
        if (this.errorTypeOptions[i].dictValue === value) {
          this.selectedObject.remark = this.errorTypeOptions[i].dictLabel
          return
        }
      }
      this.selectedObject.remark = '验'
    },
    remarkFormOpen(missId, selectedObject) {
      this.selectedObject = selectedObject
      if (this.selectedObject) {
        this.HideTip()
        this.selectedObject.errorType = null
        this.detailsDialogOpen = true
        this.selectedObject.remark = '验'
        let detailRemarkInput = document.getElementById('detailRemarkInput')
        if (detailRemarkInput) detailRemarkInput.focus()
      }
    },
    // 更新批注信息（新增或删除批注）
    handleElementComments(id, remark) {
      if (!this.checkrole(['qa'])) {
        if (!this.selectedObject.errorType) {
          alert('请选择错误类型')
          return
        }
      }
      let remarkBall = {
        taskId: this.fileList[this.currentIndex].taskId,
        mQaResultId: this.fileList[this.currentIndex].mQaResultId,
        fileName: this.fileList[this.currentIndex].fileId,
        trackId: id,
        mType:
          this.selectedObject.type + (this.selectedObject.type == '2d' ? '-' + this.selectedObject.imageIndex : ''),
        errorType: this.selectedObject.errorType,
        remark: remark,
        x: this.selectedObject.mPoint.x,
        y: this.selectedObject.mPoint.y,
        z: this.selectedObject.mPoint.z,
      }
      addRemarkBall(remarkBall).then((response) => {
        if (response.code === 200) {
          if (this.selectedObject.callback) {
            this.selectedObject.callback('success', response.markRemarkId)
          }
          if (this.selectedObject.elementInstance)
            this.selectedObject.elementInstance.markRemarkId = response.markRemarkId
          // if(this.markType === 10) {
          this.removeCache(this.fileList[this.currentIndex].mQaResultId)
          this.changePage(0)
          this.remarkListVisable = false
          this.$refs.remarkList.show(this.remarkListVisable)
          // }
          // this.msgSuccess("更新成功");
        } else {
          this.msgError(response.msg)
          if (this.selectedObject.callback) {
            this.selectedObject.callback('fail')
          }
        }
      })
      this.detailsDialogOpen = false
    },
    cancelHandleElementComments() {
      this.detailsDialogOpen = false
      if (this.selectedObject.callback) {
        this.selectedObject.callback('cancel')
      }
    },
    // 验收提交
    handleComments(ret) {
      this.fileList[this.currentIndex].mQaResult = ret
      this.fileList[this.currentIndex].remark = this.remark
      let data = {
        taskId: this.fileList[this.currentIndex].taskId,
        fileId: this.fileList[this.currentIndex].fileId,
        markResultId: this.fileList[this.currentIndex].markResultId,
        markType: this.fileList[this.currentIndex].markType,
        mQaResultId: this.fileList[this.currentIndex].mQaResultId,
        mQaResult: this.fileList[this.currentIndex].mQaResult,
        createBy: this.fileList[this.currentIndex].createBy,
        createTime: this.fileList[this.currentIndex].createTime,
        updateBy: this.fileList[this.currentIndex].updateBy,
        updateTime: this.fileList[this.currentIndex].updateTime,
        remark: this.fileList[this.currentIndex].remark,
      }
      updateResult(data).then((response) => {
        if (response.code === 200) {
          if (ret == '') {
            this.msgSuccess('批注更新成功。')
          } else if (this.currentIndex < this.fileList.length - 1) {
            this.changePage(1)
            this.msgSuccess('标注结果' + ret + '，开始载入下一张。')
          } else {
            this.msgSuccess('标注结果' + ret + '，已到达最后一张。')
          }
        } else {
          this.msgError(response.msg)
        }
      })
    },
    // 翻页函数，上一页、下一页翻页，页码跳转、选中批注后跳转页码
    changePage(num, playModel = false) {
      if (this.changeList.count() > 0) {
        this.$confirm('当前页面存在未保存的数据，是否忽略所做的修改?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'email',
        })
          .then(() => {
            this.changePage1(num, playModel)
          })
          .catch(function () {})
      } else {
        this.changePage1(num, playModel)
      }
    },
    changePage1(num, playModel = false) {
      console.debug('start change page.')
      this.changeList.clear()
      cancelAnimationFrame(this.animationFrameId)

      if (this.currentIndex + num < 0 || this.currentIndex + num >= this.fileList.length) {
        return
      }
      this.currentIndex += num

      if (this.cacheStatus && this.cacheStatus.cacheIndex <= this.currentIndex /*&& !this.cacheStatus.started*/) {
        this.cacheStatus.cacheIndex = this.currentIndex - 1
        let getAllKeysPromise = new Promise((resolve, reject) => {
          this.$getAllKeys((allkeys) => {
            resolve(allkeys)
          })
        })
        getAllKeysPromise.then((ret) => {
          this.cacheStatusVersion++
          this.pcdCache(this.$route.query.taskId, ret)
        })
      }

      this.remark = this.fileList[this.currentIndex].remark
      let query = {
        taskId: this.queryParams.taskId,
        mQaResultId: this.fileList[this.currentIndex].mQaResultId,
      }

      this.$router.replace({ path: ROUTE_PATH.editor_2d, query: query })

      this.currentStatus = this.fileList[this.currentIndex].mQaResult
        ? this.fileList[this.currentIndex].mQaResult
        : '待验收'
      this.$store.dispatch('mqaResultCurrentIndexCached', this.currentIndex)

      if (parseInt(this.markType) !== 10) {
        this.$refs.pointCloud.getPointsCloud(
          this.fileList,
          this.currentIndex,
          this.fileList[this.currentIndex].mQaResultId,
          playModel,
          this.showAttributesText
        )
      }
      if (this.imgCount > 0) {
        this.$refs.pictureList.loadDrawing(
          this.currentIndex,
          this.fileList[this.currentIndex].mQaResultId,
          this.showAttributesText
        )
      }
    },
    cacheFile(qaResultId) {
      const readValue = this.$store.state.markData.markAnnotations['MA:' + qaResultId]
      if (!readValue) {
        pointsCloudDetails(qaResultId).then((res) => {
          if (res.fileType === 'pcd') {
            this.$store.state.markData.markAnnotations.set('MA:' + qaResultId, res.annotation)
          }
        })
      } else {
        console.debug(qaResultId, ' exist.')
      }
    },
    removeCache(qaResultId) {
      this.markAnnotations.delete('MA:' + qaResultId + '')
      // this.$removeItem("MA:" + qaResultId + "");
      if (this.imgCount === 1) {
        this.markAnnotations.delete('MA:' + qaResultId + ':img')
        // this.$removeItem("MA:" + qaResultId + ":img");
      } else if (this.imgCount !== 0) {
        for (let j = 0; j < this.imgCount; j++) {
          this.markAnnotations.delete('MA:' + qaResultId + ':img' + (j + 1))
          // this.$removeItem("MA:" + qaResultId + ":img:" + (j + 1));
        }
      }
    },
    markListClick(trackId) {
      this.selectedObject.a1 = trackId
      this.sync_highlight_objects('', this.selectedObject)
    },
    // 页面全屏函数
    threejsFullScreen() {
      this.isFullscreen = !this.isFullscreen
      if (this.isFullscreen) {
        try {
          screenfull.request(document.getElementById('qaOnline'))
        } catch (err) {}
      } else {
        try {
          screenfull.toggle()
        } catch (err) {}
      }
    },
    // 返回到质检结果记录列表页面
    returnFileList(e) {
      // history.back();
      history.pushState(null, null, document.URL)
      if (e) e.preventDefault()
      this.$router.replace({
        path: ROUTE_PATH.mark_result,
        query: { taskId: this.queryParams.taskId },
      })
      for (let i = 0; i < this.$store.state.tagsView.visitedViews.length; i++) {
        if (this.$store.state.tagsView.visitedViews[i].name === 'Editor2d') {
          this.$store.dispatch('tagsView/delView', this.$store.state.tagsView.visitedViews[i])
        }
      }
    },
    // 快捷键监听函数
    keyDownHandler(e) {
      if (
        $(document.activeElement).hasClass('skip-shortcuts') ||
        $(document.activeElement).parent().hasClass('skip-shortcuts')
      ) {
        return
      }
      // enter
      if (document.activeElement.id == 'remarkInput') {
        if (e.keyCode == 13 || e.keyCode == 32) {
          e.preventDefault()
        }
        return
      }
      if (document.activeElement.id == 'detailRemarkInput') {
        if (e.keyCode == 13 || e.keyCode == 32) {
          e.preventDefault()
          if (e.keyCode == 13 && this.selectedObject && this.selectedObject.remark) {
            this.handleElementComments(
              this.selectedObject.a1 ? this.selectedObject.a1 + '' : this.selectedObject.mMarkAnnotationId + '',
              this.selectedObject.remark
            )
          }
        }
        return
      }
      if (document.activeElement.id == 'trackID') {
        if (e.keyCode == 13 && this.selectedObject && this.selectedObject.a1) {
          this.sync_highlight_objects('', this.selectedObject)
        }
      }
      if (e.keyCode == 13) {
        e.preventDefault()
        return
      }
      if (e.altKey && e.ctrlKey) {
        this.showAttributesText = !this.showAttributesText
        this.$refs.pictureList.showAttributesText2D(this.showAttributesText)
        if (this.markType !== 10) this.$refs.pointCloud.showAttributesText2D(this.showAttributesText)
        e.preventDefault()
        return
      }
      if (e.ctrlKey && e.shiftKey) {
        // if(this.selectedObject && this.selectedObject.a1) {
        this.hideOther = !this.hideOther
        // }
        // else {
        //   this.hideOther = false;
        // }
        this.$refs.pictureList.highlight_objects(undefined, this.selectedObject, false, this.hideOther)
        if (this.markType !== 10)
          this.$refs.pointCloud.highlight_objects(undefined, this.selectedObject, false, this.hideOther)
      }
      if (e.ctrlKey && e.key.toLowerCase() === 's') {
        e.preventDefault()
        this.$refs.pictureList.markSubmit()
        return
      }
      if (e.shiftKey && e.key.toLowerCase() === 'v') {
        this.copyPreviousAnnotation()
        return
      }
      if (e.altKey && e.key.toLowerCase() === 'g') {
        e.preventDefault()
        let globalPoint = this.$refs.pictureList.getGlobalAttributes()
        if (globalPoint.mMarkAnnotationId) {
          this.selectedObject = globalPoint
          this.showAttributesChangeForm()
          return
        } else {
          this.addPicMarkAnnotation(globalPoint, globalPoint.callback)
          return
        }
      }

      if (e.key.toLowerCase() === 's') {
        this.$refs.pictureList.paperToolChange('rectPoint1')
        return
      } else if (e.key.toLowerCase() === 'r') {
        this.$refs.pictureList.paperToolChange('rect')
        return
      } else if (e.key.toLowerCase() === 'q') {
        this.$refs.pictureList.paperToolChange('select')
        this.$refs.pointCloud.changeLabelTool('view')
        return
        // } else if (e.key.toLowerCase() === 'w') {
        //   this.$refs.pointCloud.changeLabelTool(null)
        //   return
      } else if (e.key.toLowerCase() === 'p') {
        this.$refs.pictureList.paperToolChange('poly')
        return
      } else if (e.key.toLowerCase() === 'l') {
        this.$refs.pictureList.paperToolChange('line')
        return
      } else if (e.key.toLowerCase() === 'o') {
        this.$refs.pictureList.paperToolChange('point1')
        return
      }

      // e
      if (e.keyCode == 69) {
        e.preventDefault()
        this.remarkFormOpen(this.selectedObject.a1, this.selectedObject)
      }
      // t
      else if (e.keyCode == 84) {
        e.preventDefault()
        let remarkInput = document.getElementById('remarkInput')
        remarkInput.focus()
      }
      // q
      // else if (e.keyCode == 81) {
      //   history.back()
      // }
      // f
      else if (e.keyCode == 70) {
        if (!this.isFullscreen) {
          this.threejsFullScreen()
        }
      }
      // a
      else if (e.keyCode == 65) {
        if (this.currentIndex >= 1 && this.loading !== true) {
          this.changePage(-1)
        }
      }
      // d
      else if (e.keyCode == 68) {
        if (this.currentIndex < this.fileList.length - 1 && this.loading !== true) {
          this.changePage(1)
        }
      }
      // // s
      // else if(e.keyCode == 83 && this.loading !== true) {
      //   this.handleComments('通过');
      // }
      // // w
      // else if(e.keyCode == 87 && this.loading !== true) {
      //   this.handleComments('驳回');
      // }
      // // r
      // else if(e.keyCode == 82 && this.loading !== true) {
      //   this.handleComments('挂起');
      // }
      // ALT + x
      else if (e.altKey && e.keyCode == 88) {
        this.showAttributesChangeForm()
      }
    },
    showAttributesChangeForm() {
      if (this.selectedObject.markType) {
        this.formOptionsInit(this.selectedObject.markType + '_')
      }

      this.annotationNameChanged(this.selectedObject.name)
      this.form.applyFullTask = false
      this.form.applyFollowResult = false
      this.form.mMarkAnnotationId = this.selectedObject.mMarkAnnotationId
      this.form.name = this.selectedObject.name
      this.form.z = null
      const _type = '_' + this.selectedObject.type
      for (let i = 1; i <= 8; i++) {
        let attribute = this.selectDictLabel(this.attributeNames, this.selectedObject.name + '_' + 'a' + i + _type)
        if (!attribute) {
          attribute = this.selectDictLabel(this.attributeNames, this.selectedObject.markType + '_' + 'a' + i + _type)
        }
        if (!attribute) {
          attribute = this.selectDictLabel(this.attributeNames, 'a' + i + _type)
        }
        this.form['a' + i] =
          attribute &&
          this.selectedObject['a' + i] &&
          this.selectedObject['a' + i] !== 'null' &&
          !this.selectedObject['a' + i].startsWith('长：')
            ? this.selectedObject['a' + i]
            : null
      }
      for (let i = 1; i <= 8; i++) {
        let attribute = this.selectDictLabel(this.attributeNames, this.selectedObject.name + '_' + 'b' + i + _type)
        if (!attribute) {
          attribute = this.selectDictLabel(this.attributeNames, this.selectedObject.markType + '_' + 'b' + i + _type)
        }
        if (!attribute) {
          attribute = this.selectDictLabel(this.attributeNames, 'b' + i + _type)
        }
        this.form['b' + i] =
          attribute &&
          this.selectedObject['b' + i] &&
          this.selectedObject['b' + i] !== 'null' &&
          !this.selectedObject['b' + i].startsWith('长：')
            ? this.selectedObject['b' + i]
            : null
      }
      this.annotationInfoDialogTitle = '属性修改'
      this.annotationInfoDialogOpen = true
    },
    isLoading(loading) {
      this.loading = loading
    },
    // 查询验收任务信息，包含属性类型、颜色类型等基础字典数据
    async qaTaskQuery() {
      let splitLine
      await getQaTask(this.queryParams.taskId).then(async (response) => {
        this.taskPath = response.data.taskName
        if (response.data.taskName.startsWith('0.')) {
          splitLine = parseFloat(response.data.taskName)
        }
        if (response.data && response.data.parentId !== 0) {
          await getQaTask(response.data.parentId).then(async (response) => {
            if (response.data) {
              this.taskPath = response.data.taskName + '@' + this.taskPath
              if (response.data.taskName.startsWith('0.')) {
                splitLine = parseFloat(response.data.taskName)
              }
              if (response.data.parentId !== '0') {
                await getQaTask(response.data.parentId).then(async (response) => {
                  if (response.data) {
                    this.taskPath = response.data.taskName + '@' + this.taskPath
                    if (response.data.taskName.startsWith('0.')) {
                      splitLine = parseFloat(response.data.taskName)
                    }
                  }
                })
              }
            }
          })
        }
      })
      const readValue = this.$store.state.markData.markAnnotations['QaTask:' + this.queryParams.taskId]
      if (readValue) {
        this.$getItem(readValue.data.markAttributes, (err, attributes) => {
          if (attributes) {
            this.attributeNames = attributes
            this.formOptionsInit()
            if (splitLine) {
              let _data = {
                dictValue: 'splitLine',
                dictLabel: splitLine,
              }
              this.attributeNames.push(_data)
            }
            this.radarView = this.selectDictLabel(this.attributeNames, 'radarView')
            this.autoAnnotation = this.selectDictLabel(this.attributeNames, 'autoAnnotation')
            this.renderType = this.selectDictLabel(this.attributeNames, 'renderType')
            this.cameraPosition = this.selectDictLabel(this.attributeNames, 'cameraPosition')
            this.highLightCubePoints = this.selectDictLabel(this.attributeNames, 'highLightCubePoints')
          } else {
            this.getDicts(readValue.data.markAttributes).then((res1) => {
              this.attributeNames = res1.data
              this.formOptionsInit()
              this.radarView = this.selectDictLabel(this.attributeNames, 'radarView')
              this.autoAnnotation = this.selectDictLabel(this.attributeNames, 'autoAnnotation')
              this.renderType = this.selectDictLabel(this.attributeNames, 'renderType')
              this.cameraPosition = this.selectDictLabel(this.attributeNames, 'cameraPosition')
              this.highLightCubePoints = this.selectDictLabel(this.attributeNames, 'highLightCubePoints')
            })
          }
        })
        this.$getItem(readValue.data.markAttributes + '_colors', (err, attributesColors) => {
          if (attributesColors) {
            this.colorNames = attributesColors
          } else {
            this.getDicts(readValue.data.markAttributes + '_colors').then((res1) => {
              this.colorNames = res1.data
            })
          }
        })
        this.markType = parseInt(readValue.data.markType)
        this.imgCount = this.markType == 9 ? 0 : this.markType == 10 ? 1 : this.markType
        this.showColorDialogVar = this.imgCount <= 1
        this.$refs.pictureList.initPaperToolPosition(this.imgCount, this.markType)
        this.getListResult()
      } else {
        getQaTask(this.queryParams.taskId).then((response) => {
          this.getDicts(response.data.markAttributes).then((res1) => {
            this.attributeNames = res1.data
            this.formOptionsInit()
            if (splitLine) {
              let _data = {
                dictValue: 'splitLine',
                dictLabel: splitLine,
              }
              this.attributeNames.push(_data)
            }
            this.radarView = this.selectDictLabel(this.attributeNames, 'radarView')
            this.autoAnnotation = this.selectDictLabel(this.attributeNames, 'autoAnnotation')
            this.renderType = this.selectDictLabel(this.attributeNames, 'renderType')
            this.cameraPosition = this.selectDictLabel(this.attributeNames, 'cameraPosition')
            this.highLightCubePoints = this.selectDictLabel(this.attributeNames, 'highLightCubePoints')
          })
          this.getDicts(response.data.markAttributes + '_colors').then((res1) => {
            this.colorNames = res1.data
          })
          this.markType = parseInt(response.data.markType)
          this.imgCount = this.markType == 9 ? 0 : this.markType == 10 ? 1 : this.markType
          this.showColorDialogVar = this.imgCount <= 1
          this.$refs.pictureList.initPaperToolPosition(this.imgCount, this.markType)
          this.getListResult()
        })
      }
    },
    formOptionsInit(pre = undefined) {
      if (pre && this.selectDictLabel(this.attributeNames, pre + 'labelName')) {
        this.formOptions.name = JSON.parse(this.selectDictLabel(this.attributeNames, pre + 'labelName')).values
      } else if (this.selectDictLabel(this.attributeNames, 'labelName')) {
        this.formOptions.name = JSON.parse(this.selectDictLabel(this.attributeNames, 'labelName')).values
      }
      if (this.selectDictLabel(this.attributeNames, 'labelAttributes'))
        this.formOptions.attributes = JSON.parse(this.selectDictLabel(this.attributeNames, 'labelAttributes')).values
      for (let j = 2; j <= 3; j++) {
        for (let i = 1; i <= 8; i++) {
          let tmp = this.selectDictLabel(this.attributeNames, pre + 'a' + i + '_' + j + 'd')
          if (!tmp) {
            tmp = this.selectDictLabel(this.attributeNames, 'a' + i + '_' + j + 'd')
          }
          if (tmp) {
            try {
              this.formOptions['a' + i + '_' + j + 'd'] = JSON.parse(tmp).values
              this.formOptions['a' + i + '_' + j + 'd_description'] = JSON.parse(tmp).typeDesc
              this.labelRules['a' + i] = [{ required: true, trigger: 'blur', message: '不能为空' }]
            } catch {}
          }
        }
        for (let i = 1; i <= 8; i++) {
          let tmp = this.selectDictLabel(this.attributeNames, pre + 'b' + i + '_' + j + 'd')
          if (!tmp) {
            tmp = this.selectDictLabel(this.attributeNames, 'b' + i + '_' + j + 'd')
          }
          if (tmp) {
            try {
              this.formOptions['b' + i + '_' + j + 'd'] = JSON.parse(tmp).values
              this.formOptions['b' + i + '_' + j + 'd_description'] = JSON.parse(tmp).typeDesc
              this.labelRules['b' + i] = [{ required: true, trigger: 'blur', message: '不能为空' }]
            } catch {}
          }
        }
      }
    },
    // 获取质检结果记录数据列表，并调用图片列表和点云视图的渲染函数进行页面渲染
    getListResult() {
      listResult(this.queryParams).then((response) => {
        this.cachePercentage = 0
        this.fileList = response.rows
        for (let i = 0; i < response.total; i++) {
          if (this.queryParams.mQaResultId == null || this.queryParams.mQaResultId == this.fileList[i].mQaResultId) {
            this.queryParams.mQaResultId = this.fileList[i].mQaResultId
            this.currentIndex = i
            this.currentStatus = this.fileList[this.currentIndex].mQaResult
              ? this.fileList[this.currentIndex].mQaResult
              : '待验收'
            this.remark = this.fileList[this.currentIndex].remark
            this.$store.dispatch('mqaResultCurrentIndexCached', this.currentIndex)
            if (parseInt(this.markType) !== 10) {
              this.$refs.pointCloud.init()
              this.$refs.pointCloud.getPointsCloud(
                this.fileList,
                this.currentIndex,
                this.fileList[i].mQaResultId,
                false,
                this.showAttributesText
              )
            }
            if (this.imgCount > 0) {
              if (this.imgCount == 1 || parseInt(this.markType) == 10) this.imgIndex = 0
              else this.imgIndex = 1
              this.$refs.pictureList.loadDrawing(this.currentIndex, this.fileList[i].mQaResultId)
            }
            break
          }
        }

        let getAllKeysPromise = new Promise((resolve, reject) => {
          this.$getAllKeys((allkeys) => {
            resolve(allkeys)
          })
        })

        getAllKeysPromise.then((ret) => {
          this.cacheStatusVersion++
          this.pcdCache(this.$route.query.taskId, ret)
        })

        this.removeAnnotationCache('MA:')
        this.removeAnnotationCache('RM:')
        try {
          getMarkAnnotations(this.$route.query.taskId).then((res) => {
            this.$store.dispatch('markAnnotationsCached', res.annotations)
          })
          listRemarkBall({ taskId: this.$route.query.taskId }).then((res) => {
            this.$store.dispatch('remarkListCached', res.rows)
          })
        } catch (e) {
          console.debug('getMarkAnnotations Exception: ' + e)
        }
        this.jumpToBottom()
      })
    },
    async pcdCache(taskId, allkeys) {
      let cacheStatusVersion = this.cacheStatusVersion
      this.cacheStatus.started = true
      this.cacheStatus.taskId = taskId
      // this.cacheStatus.cacheIndex = this.currentIndex;

      while (
        cacheStatusVersion === this.cacheStatusVersion &&
        this.cacheStatus &&
        this.cacheStatus.taskId &&
        this.fileList[this.cacheStatus.cacheIndex]
      ) {
        console.log('pcdCache version: ', cacheStatusVersion)
        if (this.cacheStatus.cacheIndex < this.currentIndex + 3) {
          let resultId = this.fileList[this.cacheStatus.cacheIndex].mQaResultId
          if (allkeys.indexOf(resultId) != -1) {
            this.cacheStatus.cacheIndex++
            this.cachePercentage = parseInt((this.cacheStatus.cacheIndex * 100) / this.fileList.length)
            continue
          }

          this.cachePercentage = parseInt((this.cacheStatus.cacheIndex * 100) / this.fileList.length)

          const blob = await getPcdFileWithCache(resultId)
          if (this.cacheStatus) {
            console.log(
              '[' + /\d\d\:\d\d\:\d\d/.exec(new Date())[0] + ']',
              'save ' + this.fileList[this.cacheStatus.cacheIndex].fileId
            )
            this.cacheStatus.cacheIndex++
          }

          try {
            for (let j = 0; j < this.imgCount; j++) {
              const image = await getImageWithCache(resultId, j + 1)
              if (image.annotation) {
                this.markAnnotations.set('MA:' + resultId + ':img' + (j + 1), image.annotation)
              }
            }
          } catch {}
        } else {
          break
        }
      }
      this.cacheStatus.started = false
      this.cachePercentage = parseInt((this.cacheStatus.cacheIndex * 100) / this.fileList.length)
    },
    // 图片列表和点云视图的公共定位缩放函数
    sync_highlight_objects(eventSource, selectedObject, cubeInfo, isZoom = true) {
      this.selectedObject = selectedObject
      this.cubeInfo = cubeInfo
      this.hideOther = false
      this.$refs.pictureList.highlight_objects(eventSource, selectedObject, isZoom, this.hideOther)
      if (this.markType !== 10)
        this.$refs.pointCloud.highlight_objects(eventSource, selectedObject, isZoom, this.hideOther)
    },
    sync_clear_highlight_objects(selectedObject) {
      this.selectedObject = selectedObject
      this.$refs.pictureList.clear_highlight_objects()
      if (this.markType !== 10) this.$refs.pointCloud.clear_highlight_objects()
    },
    // 更新右侧属性信息
    changeCubeInfo(cubeInfo) {
      this.cubeInfo = cubeInfo
    },
    jumpToBottom() {
      document.querySelector('#bottomDiv').scrollIntoView(true)
    },
    HideTip() {
      $('#focus_toolTip').css('display', 'none')
    },
    // 显示标注矩形的属性弹框信息
    ShowTip(message, x, y, tipType = 'tip') {
      if (this.detailsDialogOpen) return
      let focusTooltip = $('#focus_toolTip')
      focusTooltip.css('left', x + 'px')
      focusTooltip.css('top', y + 'px')
      focusTooltip.css('z-index', 9999)
      let attrs = message.split(';')
      let _values
      let pre = ''
      const typeName = attrs[0].split(':')[0]
      if (this.selectDictLabel(this.attributeNames, typeName + '_a1_2d')) pre = typeName + '_'
      try {
        let jsonObject = JSON.parse(this.selectDictLabel(this.attributeNames, 'labelName'))
        _values = jsonObject.values[typeName]
      } catch (e) {
        console.debug(e)
      }
      if (_values == null || _values == undefined || _values == '') _values = typeName
      if (tipType === 'tip') message = '类型：' + _values
      else message = tipType + _values
      message += '<br>'
      let _d = attrs[0].split(':')[1]
      for (let i = 1; i <= 8; i++) {
        if (attrs[i] && attrs[i] != null && attrs[i] != '' && attrs[i] != 'null') {
          try {
            let jsonObject = JSON.parse(this.selectDictLabel(this.attributeNames, pre + 'a' + i + '_' + _d + 'd'))
            let _values = jsonObject.values[attrs[i]]
            if (_values == null || _values == undefined || _values == '') _values = attrs[i]
            message += jsonObject.typeDesc + ': ' + _values + '&nbsp<br>'
          } catch {
            message += attrs[i]
          }
        }
      }
      for (let j = 9; j <= 17; j++) {
        let i = j - 8
        if (attrs[j] && attrs[j] != null && attrs[j] != '' && attrs[j] != 'null') {
          try {
            let jsonObject = JSON.parse(this.selectDictLabel(this.attributeNames, pre + 'b' + i + '_' + _d + 'd'))
            let _values = jsonObject.values[attrs[j]]
            if (_values == null || _values == undefined || _values == '') _values = attrs[j]
            message += jsonObject.typeDesc + ': ' + _values + '&nbsp<br>'
          } catch {
            message += attrs[j]
          }
        }
      }
      if (
        this.selectDictLabel(this.attributeNames, 'show3dSize') &&
        this.selectDictLabel(this.attributeNames, 'show3dSize') === 'true'
      ) {
        message += attrs[attrs.length - 1]
      }
      let headerHtml =
        "<div style='font-size:12px; color: #fec443; font-weight: bold; font-family: MicrosoftYaHei;'>" +
        message +
        '</div>'
      let effectHtml = "<div style='font-size:12px;margin-top:3px;' >" + '</div>'
      this.toolTopbody = headerHtml + effectHtml
      focusTooltip.css('display', 'block')
    },
    ShowAttributesText(show) {
      let opacity = show ? 1 : 0
      for (let m = 0; m < this.mainLayer.length; m++) {
        if (!this.mainLayer[m]) continue
        let items = this.mainLayer[m].getItems()
        for (let i = 0; i < items.length; i++) {
          if (items[i].textObject) {
            items[i].textObject.opacity = opacity
          }
        }
      }
    },
    contextmenuHandler(e) {
      e.preventDefault()
    },
    onWindowResize() {
      this.$refs.pointCloud.onWindowResize()
      this.$refs.pictureList.onWindowResize()
    },
    animation() {
      if (this.playStarted) {
        if (performance.now() - this.lastPlayTime > 50) {
          this.playFunction()
        }
        requestAnimationFrame(this.animation)
      }
    },
    startPlay() {
      this.playStarted = true
      this.lastPlayTime = performance.now()
      if (this.interval === undefined) {
        this.interval = requestAnimationFrame(this.animation)
      }
    },
    playFunction() {
      if (this.currentIndex < this.fileList.length) {
        if (this.$store.state.markData.playStatus.pic && this.$store.state.markData.playStatus.pcd) {
          this.$store.state.markData.playStatus.pic = false
          this.$store.state.markData.playStatus.pcd = false
          this.saveImage('html2canvas', 'test')
          let readValue = this.markAnnotations.get('MA:' + this.fileList[this.currentIndex].mQaResultId + '')
          if (readValue) {
            this.$refs.pointCloud
              .getPointsCloud(
                this.fileList,
                this.currentIndex,
                this.fileList[this.currentIndex].mQaResultId,
                true,
                this.showAttributesText
              )
              .then(() => {
                let query = {
                  taskId: this.queryParams.taskId,
                  mQaResultId: this.fileList[this.currentIndex].mQaResultId,
                }
                this.$router.replace({
                  path: ROUTE_PATH.editor_2d,
                  query: query,
                })
                if (this.imgCount > 0) {
                  this.$refs.pictureList.loadDrawing(
                    this.currentIndex,
                    this.fileList[this.currentIndex].mQaResultId,
                    this.showAttributesText,
                    true
                  )
                }
                if (this.currentIndex < this.fileList.length) this.currentIndex++
                this.lastPlayTime = performance.now()
              })
          }
        }
      } else {
        this.saveImage('html2canvas', 'test')
        this.encoder.compile(false, (output) => {
          const url = (window.webkitURL || window.URL).createObjectURL(output)
          let a = document.createElement('a')
          a.style.display = 'none'
          a.setAttribute('href', url)
          a.setAttribute('download', this.taskName + '_w.mp4')
          document.body.appendChild(a)
          a.click()
          URL.revokeObjectURL(output)
          document.body.removeChild(a)
        })
        this.playStarted = false
        this.currentIndex = this.fileList.length - 1
        cancelAnimationFrame(this.interval)
        this.interval = undefined
      }
    },
    pausePlay() {
      this.playStarted = false
      cancelAnimationFrame(this.interval)
      this.interval = undefined
      this.changePage(0)
    },
    saveChange() {
      let changeStore = this.changeList.fetch()
      for (let key in changeStore) {
        let tmp = changeStore[key]
        if (tmp.action && tmp.action === 'update') {
          if (tmp.type === 'path' && tmp.info.mMarkAnnotationId && tmp.info.markType === 'rect') {
            let path = tmp.info
            let x = '',
              y = ''
            let tmpPoint = path.pointToLocal(path.point1.segments[0].point)
            x += tmpPoint.x + ';'
            y += tmpPoint.y + ';'
            tmpPoint = path.pointToLocal(path.point3.segments[0].point)
            x += tmpPoint.x + ';'
            y += tmpPoint.y + ';'
            if (path.midPath) {
              tmpPoint = path.pointToLocal(path.midPath.segments[0].point)
              x += tmpPoint.x + ';'
              y += tmpPoint.y + ';'
            }
            if (path.rangePath) {
              tmpPoint = path.pointToLocal(path.rangePath.segments[0].point)
              x += tmpPoint.x + ';'
              y += tmpPoint.y + ';'
              tmpPoint = path.pointToLocal(path.rangePath.segments[1].point)
              x += tmpPoint.x + ';'
              y += tmpPoint.y + ';'
            }
            if (path.rectPoint1) {
              tmpPoint = path.pointToLocal(path.rectPoint1.segments[0].point)
              x += tmpPoint.x + ';'
              y += tmpPoint.y + ';'
            }
            let params = {
              mMarkAnnotationId: path.mMarkAnnotationId,
              x: x.slice(0, x.length - 1),
              y: y.slice(0, y.length - 1),
            }
            updateAnnotation(params)
          } else if (
            tmp.type === 'path' &&
            tmp.info.mMarkAnnotationId &&
            (tmp.info.markType === 'poly' || tmp.info.markType === 'line')
          ) {
            let path = tmp.info
            let x = '',
              y = ''
            for (let i = 0; i < path.segments.length; i++) {
              let tmpPoint = path.pointToLocal(path.segments[i].point)
              x += tmpPoint.x + ';'
              y += tmpPoint.y + ';'
            }
            let params = {
              mMarkAnnotationId: path.mMarkAnnotationId,
              x: x.slice(0, x.length - 1),
              y: y.slice(0, y.length - 1),
            }
            updateAnnotation(params)
          } else if (tmp.type === 'path' && tmp.info.mMarkAnnotationId && tmp.info.markType === 'point1') {
            let path = tmp.info
            let tmpPoint = path.pointToLocal(path.segments[0].point)
            let x = tmpPoint.x + ';'
            let y = tmpPoint.y + ';'
            let params = {
              mMarkAnnotationId: path.mMarkAnnotationId,
              x,
              y,
            }
            updateAnnotation(params)
          }
        } else if (tmp.action && tmp.action === 'delete') {
          deleteAnnotation(tmp.info.mMarkAnnotationId)
        } else if (tmp.action && tmp.action === 'addNew') {
          const annotation = tmp.info.toDBObject()
          if (annotation.mQaResultId) {
            addAnnotation(annotation)
          } else {
            this.msgError('页面加载异常，请重新标注。')
          }
        }
        this.changeList.remove(key)
      }
      this.changeList.clear()
      this.removeCache(this.fileList[this.currentIndex].mQaResultId)
      this.changePage(0)
    },
    addSplitMarkAnnotation(pointsIndex, minusPointsIndex, callback) {
      this.$confirm('需要将选中的点作为新目标创建还是更新已有记录？', '提交', {
        confirmButtonText: '新建',
        cancelButtonText: '更新',
        type: 'email',
      })
        .then(() => {
          if (pointsIndex && pointsIndex.length > 0) {
            this.selectedObject = {
              name: '',
              type: '3d',
            }
            this.form.mMarkAnnotationId = null
            this.form.mQaResultId = this.fileList[this.currentIndex].mQaResultId
            this.form.name = this.selectedObject.name
            this.form.x = pointsIndex.toString()
            this.form.z = 'split'
            for (let i = 1; i <= 8; i++) {
              this.form['a' + i] = null
            }
            this.form.fileType = '3d'
            this.form.fileName = this.fileList[this.currentIndex].fileId
            this.form.callback = callback
            this.annotationInfoDialogTitle = '新建点云分割目标'
            this.annotationInfoDialogOpen = true
          }
        })
        .catch(() => {
          this.queryAnnotationList()
          this.updateSplitInfoForm.pointsIndex = pointsIndex
          this.updateSplitInfoForm.minusPointsIndex = minusPointsIndex
          this.updateSplitInfoForm.callback = callback
          this.updateSplitInfoDialogOpen = true
        })
    },
    submitUpdateSplitInfoForm() {
      let tobeUpdated = null
      this.annotationList.forEach((element) => {
        if (element.mMarkAnnotationId == this.updateSplitInfoForm.mMarkAnnotationId) tobeUpdated = element
      })
      let originalPointsIndex = tobeUpdated.x.split(',')
      let tmpPoints = []
      originalPointsIndex.forEach((index) => {
        if (this.updateSplitInfoForm.minusPointsIndex.indexOf(parseInt(index)) == -1) tmpPoints.push(parseInt(index))
      })
      this.updateSplitInfoForm.pointsIndex.forEach((index) => {
        if (tmpPoints.indexOf(index) == -1) tmpPoints.push(index)
      })
      tobeUpdated.x = tmpPoints.toString()
      updateAnnotation(tobeUpdated).then((response) => {
        if (response.code == 200) {
          // this.updateSplitInfoForm.callback(params);
          this.msgSuccess('更新成功')
          this.removeCache(this.fileList[this.currentIndex].mQaResultId)
          this.changePage(0)
        } else {
          this.msgError(response.msg)
        }
        this.updateSplitInfoDialogOpen = false
      })
    },
    cancelUpdateSplitInfoForm() {
      if (this.updateSplitInfoForm.callback) {
        const params = {
          form: null,
          ret: 'cancel',
        }
        this.updateSplitInfoForm.callback(params)
      }
    },
    addPicMarkAnnotation(picMarkAnnotation, callback) {
      this.selectedObject.type = '2d'
      this.form.mMarkAnnotationId = null
      this.form.mQaResultId = this.fileList[this.currentIndex].mQaResultId
      this.form.z = picMarkAnnotation.toDBObject().z
      let labelTypeName = picMarkAnnotation.toDBObject().z + '_labelName'
      this.formOptionsInit(picMarkAnnotation.toDBObject().z + '_')
      if (this.selectDictLabel(this.attributeNames, labelTypeName)) {
        this.formOptions.name = JSON.parse(this.selectDictLabel(this.attributeNames, labelTypeName)).values
      }
      for (let i = 1; i <= 8; i++) {
        this.form['a' + i] = null
      }
      for (let i = 1; i <= 8; i++) {
        this.form['b' + i] = null
      }
      this.form.fileType = '2d'
      this.form.fileName = this.fileList[this.currentIndex].fileId
      this.form.instance = picMarkAnnotation
      this.form.callback = callback
      this.annotationInfoDialogTitle = '新建二维标注目标'
      this.annotationInfoDialogOpen = true
    },
    submitAnnotations(annotations) {
      this.saveChange()
    },
    submitUpdateForm() {
      this.$refs.form.validate((valid) => {
        if (valid) {
          if (this.form.callback) {
            const params = {
              form: this.form,
              ret: 'confirm',
            }
            this.form.callback(params)
          }
          if (!this.form.mMarkAnnotationId) {
            if (this.form.fileType === '3d') {
              // if(this.splitMap.has(this.form.name)) {
              //   this.splitMap.get(this.form.name).push(...this.form.x);
              // }
              // else{
              //   this.splitMap.set(this.form.name, this.form.x);
              // }
              // this.resetUpdateForm();
              addAnnotation(this.form).then((response) => {
                if (response.code == 200) {
                  this.msgSuccess('标注成功')
                  this.removeCache(this.fileList[this.currentIndex].mQaResultId)
                  this.changePage(0)
                  this.resetUpdateForm()
                } else {
                  this.msgError(response.msg)
                  this.resetUpdateForm()
                }
              })
            } else if (this.form.fileType === '2d') {
              let rect = this.form.instance
              rect.name = this.form.name
              rect.a1 = this.form.a1
              rect.a2 = this.form.a2
              rect.a3 = this.form.a3
              rect.a4 = this.form.a4
              rect.a5 = this.form.a5
              rect.a6 = this.form.a6
              rect.a7 = this.form.a7
              rect.a8 = this.form.a8
              rect.b1 = this.form.b1
              rect.b2 = this.form.b2
              rect.b3 = this.form.b3
              rect.b4 = this.form.b4
              rect.b5 = this.form.b5
              rect.b6 = this.form.b6
              rect.b7 = this.form.b7
              rect.b8 = this.form.b8
              this.form.instance = null
              this.resetUpdateForm()
            }
          } else {
            let labels = {}
            for (let i = 1; i <= 8; i++) {
              labels['a' + i] = this.form['a' + i]
              labels['b' + i] = this.form['b' + i]
            }
            this.form.labels = JSON.stringify(labels)
            updateAnnotationAttributes(this.form).then((response) => {
              if (response.code === 200) {
                this.msgSuccess('修改成功')
                this.removeCache(this.fileList[this.currentIndex].mQaResultId)
                this.changePage(0)
                this.resetUpdateForm()
              } else {
                this.msgError(response.msg)
                this.resetUpdateForm()
              }
            })
          }
        }
      })
    },
    cancelUpdateForm() {
      if (this.form.callback) {
        const params = {
          form: this.form,
          ret: 'cancel',
        }
        this.form.callback(params)
      }
      this.resetUpdateForm()
    },
    resetUpdateForm() {
      this.annotationInfoDialogOpen = false
      this.form = {
        mMarkAnnotationId: undefined,
        name: undefined,
        a1: undefined,
        a2: undefined,
        a3: undefined,
        a4: undefined,
        a5: undefined,
        a6: undefined,
        a7: undefined,
        a8: undefined,
      }
      this.resetForm('form')
    },
    //图片格式转换
    dataURLToBlob(dataurl) {
      let arr = dataurl.split(',')
      let mime = arr[0].match(/:(.*?);/)[1]
      let bstr = atob(arr[1])
      let n = bstr.length
      let u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      return new Blob([u8arr], { type: mime })
    },
    saveImage(divText, imgText) {
      let canvasID = this.$refs[divText]
      // let that = this;
      // let a = document.createElement('a');
      html2canvas(canvasID).then((canvas) => {
        // let dom = document.body.appendChild(canvas);
        // dom.style.display = 'none';
        // a.style.display = 'none';
        // document.body.removeChild(dom);
        // let blob = that.dataURLToBlob(dom.toDataURL('image/png'));
        // let url = URL.createObjectURL(blob);
        this.encoder.add(canvas)
        // a.setAttribute('href', url);
        // //这块是保存图片操作  可以设置保存的图片的信息
        // a.setAttribute('download', imgText + '.png');
        // document.body.appendChild(a);
        // a.click();
        // URL.revokeObjectURL(blob);
        // document.body.removeChild(a);
      })
    },
    queryAnnotationList() {
      this.annotationQueryParams.mQaResultId = this.fileList[this.currentIndex].mQaResultId
      annotationList(this.annotationQueryParams).then((res) => {
        if (res.code == '200') {
          res.rows.forEach((row) => {
            if (row.labels) {
              try {
                const labelsJson = JSON.parse(row.labels)
                for (let i = 1; i <= 8; i++) {
                  row['a' + i] = labelsJson['a' + i]
                  row['b' + i] = labelsJson['b' + i]
                }
              } catch {}
            }
          })
          this.annotationTotal = res.total
          this.annotationList = res.rows
          // this.annotationDialogVisible = true
        } else {
          this.msgError(res.msg)
        }
      })
    },
    handleAnnotationUpdate(row) {
      this.form.applyFullTask = false
      this.form.applyFollowResult = false
      this.form.mMarkAnnotationId = row.mMarkAnnotationId
      this.form.mQaResultId = row.mQaResultId
      this.form.fileType = row.fileType
      this.selectedObject.type = row.fileType
      this.form.fileName = row.fileName
      let labelTypeName = row.annotationType + '_labelName'
      this.formOptionsInit(row.annotationType + '_')
      if (this.selectDictLabel(this.attributeNames, labelTypeName)) {
        this.formOptions.name = JSON.parse(this.selectDictLabel(this.attributeNames, labelTypeName)).values
      }
      this.form.name = row.name
      if (row.labels) {
        try {
          const attributesJson = JSON.parse(row.labels)
          for (let i = 1; i <= 8; i++) {
            this.form['a' + i] = attributesJson['a' + i]
          }
          for (let i = 1; i <= 8; i++) {
            this.form['b' + i] = attributesJson['b' + i]
          }
        } catch {
          console.log(row.labels, 'parse error')
          for (let i = 1; i <= 8; i++) {
            this.form['a' + i] = row['a' + i]
          }
          for (let i = 1; i <= 8; i++) {
            this.form['b' + i] = null
          }
        }
      } else {
        for (let i = 1; i <= 8; i++) {
          this.form['a' + i] = row['a' + i]
        }
        for (let i = 1; i <= 8; i++) {
          this.form['b' + i] = null
        }
      }
      this.form.callback = (params) => {
        if (params.ret === 'confirm') {
          // this.queryAnnotationList()
          this.annotationDialogVisible = false
        }
      }
      this.annotationInfoDialogOpen = true
    },
    handleAnnotationDelete(row) {
      this.$confirm('该操作将删除选中的记录，且不可恢复。确定删除?', '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => {
          const mMarkAnnotationIds = row.mMarkAnnotationId || this.ids
          deleteAnnotation(mMarkAnnotationIds).then((res) => {
            if (res.code == '200') {
              this.msgSuccess(res.msg)
              annotationList(this.annotationQueryParams).then((res) => {
                if (res.code == '200') {
                  this.annotationList = res.rows
                }
              })
              this.removeCache(this.fileList[this.currentIndex].mQaResultId)
              this.changePage(0)
            } else {
              this.msgError(res.msg)
            }
          })
        })
        .catch(() => {})
    },
    annotationNameFormatter(row) {
      let jsonObject = JSON.parse(this.selectDictLabel(this.attributeNames, 'labelName'))
      if (jsonObject.values.hasOwnProperty(row.name)) return jsonObject.values[row.name]
      else return row.name
    },
    annotationAttributeFormatter(row, col) {
      const an = col.property + '_' + row.fileType
      const anName = row.name + '_' + an
      const anType = row.annotationType + '_' + an
      try {
        const jsonObject = JSON.parse(this.selectDictLabel(this.attributeNames, anName))
        if (jsonObject.values.hasOwnProperty(row[col.property])) return jsonObject.values[row[col.property]]
      } catch {}
      try {
        const jsonObject = JSON.parse(this.selectDictLabel(this.attributeNames, anType))
        if (jsonObject.values.hasOwnProperty(row[col.property])) return jsonObject.values[row[col.property]]
      } catch {}
      try {
        const jsonObject = JSON.parse(this.selectDictLabel(this.attributeNames, an))
        if (jsonObject.values.hasOwnProperty(row[col.property])) return jsonObject.values[row[col.property]]
      } catch {}
      return row[col.property]
    },
    handleSelectionChange(selection) {
      this.multiple = !selection.length
      this.ids = selection.map((item) => item.mMarkAnnotationId)
      this.$refs.pictureList.showMarkAnnotations(this.ids)
      if (this.markType !== 10) this.$refs.pointCloud.showMarkAnnotations(this.ids)
    },
    annotationNameChanged(value) {
      for (let j = 2; j <= 3; j++) {
        for (let i = 1; i <= 8; i++) {
          let tmp = this.selectDictLabel(this.attributeNames, value + '_a' + i + '_' + j + 'd')
          let markType = this.form.z ? this.form.z : this.selectedObject.markType
          let markTypeAttr = this.selectDictLabel(this.attributeNames, markType + '_a' + i + '_' + j + 'd')
          let traditional = this.selectDictLabel(this.attributeNames, 'a' + i + '_' + j + 'd')
          if (tmp) {
            try {
              this.formOptions['a' + i + '_' + j + 'd'] = JSON.parse(tmp).values
              this.formOptions['a' + i + '_' + j + 'd_description'] = JSON.parse(tmp).typeDesc
              this.labelRules['a' + i] = [{ required: true, trigger: 'blur', message: '不能为空' }]
            } catch {}
          } else if (markTypeAttr) {
            try {
              this.formOptions['a' + i + '_' + j + 'd'] = JSON.parse(markTypeAttr).values
              this.formOptions['a' + i + '_' + j + 'd_description'] = JSON.parse(markTypeAttr).typeDesc
              this.labelRules['a' + i] = [{ required: true, trigger: 'blur', message: '不能为空' }]
            } catch {}
          } else if (traditional) {
            try {
              this.formOptions['a' + i + '_' + j + 'd'] = JSON.parse(traditional).values
              this.formOptions['a' + i + '_' + j + 'd_description'] = JSON.parse(traditional).typeDesc
              this.labelRules['a' + i] = [{ required: true, trigger: 'blur', message: '不能为空' }]
            } catch {}
          } else {
            this.formOptions['a' + i + '_' + j + 'd'] = null
            this.formOptions['a' + i + '_' + j + 'd_description'] = null
          }
        }

        for (let i = 1; i <= 8; i++) {
          let tmp = this.selectDictLabel(this.attributeNames, value + '_b' + i + '_' + j + 'd')
          let markType = this.form.z ? this.form.z : this.selectedObject.markType
          let markTypeAttr = this.selectDictLabel(this.attributeNames, markType + '_b' + i + '_' + j + 'd')
          let traditional = this.selectDictLabel(this.attributeNames, 'b' + i + '_' + j + 'd')
          if (tmp) {
            try {
              this.formOptions['b' + i + '_' + j + 'd'] = JSON.parse(tmp).values
              this.formOptions['b' + i + '_' + j + 'd_description'] = JSON.parse(tmp).typeDesc
              this.labelRules['b' + i] = [{ required: true, trigger: 'blur', message: '不能为空' }]
            } catch {}
          } else if (markTypeAttr) {
            try {
              this.formOptions['b' + i + '_' + j + 'd'] = JSON.parse(markTypeAttr).values
              this.formOptions['b' + i + '_' + j + 'd_description'] = JSON.parse(markTypeAttr).typeDesc
              this.labelRules['b' + i] = [{ required: true, trigger: 'blur', message: '不能为空' }]
            } catch {}
          } else if (traditional) {
            try {
              this.formOptions['b' + i + '_' + j + 'd'] = JSON.parse(traditional).values
              this.formOptions['b' + i + '_' + j + 'd_description'] = JSON.parse(traditional).typeDesc
              this.labelRules['b' + i] = [{ required: true, trigger: 'blur', message: '不能为空' }]
            } catch {}
          } else {
            this.formOptions['b' + i + '_' + j + 'd'] = null
            this.formOptions['b' + i + '_' + j + 'd_description'] = null
          }
        }
      }
    },
    onAnnotationRowSelect(row, column, event) {
      if (row.fileType === '3d') {
        this.$refs.pointCloud.focusObject(row)
      }
    },
    getLabelName(dictValue) {
      let ret = dictValue
      try {
        let jsonObject = JSON.parse(this.selectDictLabel(this.attributeNames, 'labelName'))
        ret = jsonObject.values[ret]
      } catch {}
      return ret
    },
    copyPreviousAnnotation() {
      if (this.currentIndex > 0) {
        console.log(this.fileList[this.currentIndex - 1].mQaResultId, this.fileList[this.currentIndex].mQaResultId)
        copyPreviousAnnotation(
          this.fileList[this.currentIndex - 1].mQaResultId,
          this.fileList[this.currentIndex].mQaResultId
        ).then((ret) => {
          if (ret.code == 200) {
            this.removeCache(this.fileList[this.currentIndex].mQaResultId)
            this.changePage(0)
            this.msgSuccess(ret.msg)
          } else {
            this.msgError(ret.msg)
          }
        })
      }
    },
  },
  // 捕获界面刷新事件，清除标注结果缓存
  beforeRouteEnter(to, from, next) {
    next((vm) => {
      if (from.name === null) {
        vm.removeAnnotationCache('MA:' + to.query.mQaResultId)
      }
    })
  },
  created() {
    this.encoder = new window.Whammy.Video(5)
    if (!this.$route.query.taskId || !this.$route.query.mQaResultId) this.$router.go(-1)
    this.queryParams.taskId = this.$route.query.taskId
    this.queryParams.mQaResultId = this.$route.query.mQaResultId
    this.selectedObjectA1 = this.$route.query.selectedObjectA1
    window.addEventListener('contextmenu', this.contextmenuHandler, false)
    this.$store.dispatch('app/closeSideBar', { withoutAnimation: true })
    this.getDicts('mark_result_error_type').then((response) => {
      this.errorTypeOptions = response.data
    })

    //在页面刷新时将paperToolPosition的信息保存到store里，再由全局main.js保存到localStorage里
    window.addEventListener('beforeunload', () => {
      localStorage.setItem('currentIndex', this.currentIndex)
    })
  },
  mounted() {
    this.qaTaskQuery()
    // this.queryAnnotationList();
    window.addEventListener('resize', this.onWindowResize, false)
    document.addEventListener('keydown', this.keyDownHandler, false)
    screenfull.on('change', (event) => {
      this.isFullscreen = screenfull.isFullscreen
    })
  },
  destroyed() {
    this.cacheStatusVersion = 0
    this.cacheStatus = {
      taskId: null,
      cacheIndex: 0,
    }
    cancelAnimationFrame(this.animationFrameId)
    window.removeEventListener('contextmenu', this.contextmenuHandler, false)
    window.removeEventListener('resize', this.onWindowResize, false)
    document.removeEventListener('keydown', this.keyDownHandler, false)
  },
}
</script>
<style lang="scss" scoped>
html,
body {
  width: 100%;
  height: 100%;
}

/* Scale canvas with resize attribute to full size */
canvas[resize] {
  width: 100%;
  height: auto;
}

.special_focus_toolTip {
  z-index: 7;
  position: absolute;
  display: none;
  width: 180px;
  height: 240px;
  border-style: solid;
  transition: left 0.4s cubic-bezier(0.23, 1, 0.32, 1), top 0.4s cubic-bezier(0.23, 1, 0.32, 1);
  background-color: rgba(50, 50, 50, 0.701961);
  border-width: 0px;
  border-color: #333333;
  border-radius: 4px;
  color: #ffffff;
  font-style: normal;
  font-variant: normal;
  font-weight: normal;
  font-stretch: normal;
  font-size: 14px;
  font-family: 'Microsoft YaHei';
  line-height: 21px;
  padding: 10px 10px;
  pointer-events: none;
}

.icon-list {
  height: calc(100vh - 155px);
  overflow-y: auto;
  .color-name {
    height: 30px;
    line-height: 30px;
    // margin-bottom: -5px;
    cursor: pointer;
    width: 50%;
    float: left;
    span {
      vertical-align: 0.3em;
      fill: currentColor;
      margin-left: 5px;
    }
  }
}
.bottom-div {
  bottom: 0;
  height: 46px;
  line-height: 46px;
  padding: 0 10px;
  background: #fff;
  .el-form-item {
    margin: 0;
    display: inline-grid;
    vertical-align: middle;
  }
  .filename {
    word-wrap: break-word;
    word-break: break-all;
    display: flex;
    align-items: center;
    height: 46px;
    span {
      line-height: 18px;
    }
  }
  .color-name-btn {
    display: flex;
    align-items: center;
    height: 46px;
    margin-left: 15px;
  }
}

/*  dialog*/
.el-dialog__header {
  padding: 15px 20px 15px;
}
.el-dialog__headerbtn {
  top: 15px;
}

/*dialog header*/
.el-dialog__header {
  background: #e3eaed;
}
.avue-crud__dialog__header {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
  -webkit-box-pack: justify;
  -ms-flex-pack: justify;
  justify-content: space-between;
}
.el-dialog__title {
  color: rgba(0, 0, 0, 0.85);
  font-weight: 500;
  word-wrap: break-word;
}
.avue-crud__dialog__menu {
  padding-right: 20px;
  float: left;
}
.avue-crud__dialog__menu i {
  color: #909399;
  font-size: 15px;
}
.el-icon-full-screen {
  cursor: pointer;
}
.el-icon-full-screen:before {
  content: '\e719';
}
</style>
